/*
 * Copyright 2007 Eloff Enterprises
 *
 * Licensed under the BSD License (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://rwig.googlecode.com/files/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.  See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * Originally developed by Daniel Eloff.
 *
 */

#ifdef __cplusplus
extern "C" {
#endif

#include "rwig_utils.h"

rwig_str RWIG_STR_NULL;

void bad_type(PyObject * obj) {
	PyObject * ty = PyObject_Str((PyObject*)obj->ob_type); // Creates a new Python String, decref it!
	if(ty) {
		PyErr_Format(PyExc_ValueError, "Cannot convert type %s to integer.", PyString_AS_STRING(ty));
		Py_DECREF(ty);
	}	
}

int long_to_int(long n) {
	int i = (int)n;
	if((long)i == n)				
		return i; // No overflow
	else {
		PyErr_SetString(PyExc_ValueError, "Overflow when converting long to int");
		return -1;
	}
}

float dbl_to_flt(double d) {
	if(d < FLT_MIN || d > FLT_MAX) {
		PyErr_SetString(PyExc_ValueError, "Overflow when converting double to float");
		return 0.0f;
	}
	else
		return (float)d;
}

int py_to_int(PyObject * obj) {
	/* Convert a Python object to a C integer if possible */
	int rv = -1; // Error return

	if(!obj) {
		PyErr_SetString(PyExc_ValueError, "Cannot convert NULL pointer.");
		return rv;
	}		

	if(PyInt_Check(obj)) {
		long l_ret = PyInt_AsLong(obj); // Checks for overflow
		if(!PyErr_Occurred())
			rv = long_to_int(l_ret);
	}
	else if(PyLong_Check(obj)) {
		long l_ret = PyLong_AsLong(obj); // Checks for overflow
		if(!PyErr_Occurred())
			rv = long_to_int(l_ret);
	}
	else {
		bad_type(obj);
	}

	return rv;
}

float py_to_float(PyObject * obj) {
	float rv = 0.0f; // Error return

	if(!obj) {
		PyErr_SetString(PyExc_ValueError, "Cannot convert NULL pointer.");
		return rv;
	}

	if(PyFloat_Check(obj)) {
		double d = PyFloat_AsDouble(obj);
		if(!PyErr_Occurred())
			rv = dbl_to_flt(d);
	}
	else {
		bad_type(obj);
	}

	return rv;
}

double py_to_double(PyObject * obj) {
	double rv = 0.0; // Error return

	if(!obj) {
		PyErr_SetString(PyExc_ValueError, "Cannot convert NULL pointer.");
		return rv;
	}

	if(PyFloat_Check(obj)) {
		double d = PyFloat_AsDouble(obj);
		if(!PyErr_Occurred())
			rv = d;
	}
	else {
		bad_type(obj);
	}

	return rv;
}

rwig_str py_to_rwig_str(PyObject * obj) {
	/* Convert a Python object to a rwig string (must be freed with free()!). */
	PyObject * s = PyObject_Str(obj);
	rwig_str str = RWIG_STR_NULL;

	if(!s)
		return str;

	str.len = PyObject_Length(s);
	str.buf = (char*)malloc(str.len);
	if(str.buf)
		memcpy(str.buf, PyString_AS_STRING(s), str.len);

	Py_DECREF(s);
	return str;
}

char * py_to_str(PyObject * obj) {
	/* Convert a Python object to a null-terminated string (must be freed with free()!). */
	PyObject * s = PyObject_Str(obj);
	int len = 0;
	char * buf = NULL;

	if(!s)
		return NULL;

	len = PyObject_Length(s);
	buf = (char*)malloc(len+1);
	if(buf) {
		memcpy(buf, PyString_AS_STRING(s), len);
		buf[len] = '\0';
	}

	Py_DECREF(s);
	return buf;
}

/*RWIG_STR_NULL.buf = 0;
RWIG_STR_NULL.len = 0;*/

#ifdef __cplusplus
} // extern "C"
#endif